import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.Border;

public class GUIBoard extends JFrame implements ActionListener {
	JPanel[][] panels = new JPanel[3][3];
	private Tile[][] tiles = new Tile[9][9];
	private JPanel topPanel = new JPanel();
	private JPanel controlPanel = new JPanel();
	private int[][] nums = new int[9][9];
	JButton checkButton;
	JButton difButton;
	JButton newButton;
	JPanel entryPanel;
	JRadioButton playRadio;
	JRadioButton solveRadio;
	ButtonGroup startGroup;
	JButton okButton;
	Board b;

	public GUIBoard(Board b1) {
		this.b = b1;

		topPanel.setLayout(new GridLayout(3, 3));
		this.setLayout(new BorderLayout());

		setupBoard();
		setupControlPanel();

		add(topPanel, BorderLayout.CENTER);
		add(controlPanel, BorderLayout.SOUTH);

		setupFrame();

		remove(topPanel);
		remove(controlPanel);

		JPanel startPanel = createStartPanel();
		add(startPanel, BorderLayout.CENTER);
		startPanel.setVisible(true);

	}

	public JPanel createStartPanel() {
		entryPanel = new JPanel();
		entryPanel.setLayout(new BorderLayout());

		startGroup = new ButtonGroup();

		playRadio = new JRadioButton("Play a sudoku game");
		playRadio.addActionListener(this);
		startGroup.add(playRadio);

		solveRadio = new JRadioButton("Solve a sudoku");
		solveRadio.addActionListener(this);
		startGroup.add(solveRadio);

		okButton = new JButton("Ok");
		okButton.addActionListener(this);

		startGroup.add(playRadio);
		startGroup.add(solveRadio);

		JPanel centerPanel = new JPanel();
		centerPanel.setLayout(new GridLayout(0, 1));

		centerPanel.add(playRadio);
		centerPanel.add(solveRadio);
		entryPanel.add(centerPanel, BorderLayout.CENTER);
		entryPanel.add(okButton, BorderLayout.SOUTH);
		add(entryPanel);
		entryPanel.setVisible(true);
		this.setVisible(true);
		return entryPanel;

	}

	private void setupBoard() {
		setupBoxPanels();
		setupTiles();

	}

	private void setupBoxPanels() {
		for (int x = 0; x < 3; x++) {
			for (int y = 0; y < 3; y++) {
				panels[x][y] = new JPanel();
				Border border = BorderFactory.createLineBorder(Color.BLACK);
				panels[x][y].setBorder(border);
				panels[x][y].setLayout(new GridLayout(3, 3));
				topPanel.add(panels[x][y]);
			}
		}
	}

	private void setupTiles() {
		for (int x = 0; x < 9; x++) {
			for (int y = 0; y < 9; y++) {
				Tile t = new Tile(b.userBoard[x][y]);

				tiles[x][y] = t;
				tiles[x][y].addActionListener(this);
				panels[x / 3][y / 3].add(tiles[x][y]);
			}
		}
	}

	private void setupFrame() {
		setTitle("Sudoku");
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		final int WIDTH = 500;
		final int HEIGHT = 550;
		this.setSize(WIDTH, HEIGHT);
		this.setVisible(true);
	}

	private void setupControlPanel() {
		newButton = new JButton("New Game");
		newButton.addActionListener(this);

		checkButton = new JButton("Submit");
		checkButton.addActionListener(this);

		difButton = new JButton("Difficulty");
		difButton.addActionListener(this);
		controlPanel.add(newButton);

		controlPanel.add(checkButton);
		controlPanel.add(difButton);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		if (source == difButton) {
			setDifficulty();

		} else if (source == newButton) {
			restartGame();
		} else if (source == checkButton) {
			updateUserBoard();
			if (checkButton.getText().equals("Submit")) {
				checkWin();
			} else {
				b.solve(b.userBoard);
				regenerateBoard();
			}
		} else if (source == okButton) {
			System.out.println("Ok Button");
			setupGame();
		} else {
			changeNumber(source);
		}
	}

	private void updateUserBoard() {
		for (int x = 0; x < 9; x++) {
			for (int y = 0; y < 9; y++) {
				b.userBoard[x][y] = tiles[x][y].getNum();
			}
		}
	}

	private void setDifficulty() {
		int num = -1;
		while (num < 1 || num > 3) {
			num = Integer
					.valueOf(JOptionPane
							.showInputDialog("What level of difficulty would you like?"));
		}
		b.userBoard(num);
		regenerateBoard();
	}

	private void restartGame() {
		b = Board.creator();
		regenerateBoard();
	}

	private void checkWin() {
		System.err.println("KEY");
		System.out.println(b);
		System.out.println();
		System.err.println("User Board");
		b.printBoard(b.userBoard);
		if (b.win(b.userBoard)) {
			System.out.println("You won!");
			JOptionPane.showMessageDialog(topPanel, "You Won!");
		}

		else {
			JOptionPane.showMessageDialog(topPanel, "Try Again");
			System.out.println("Try again");
		}
	}

	private void setupGame() {
		if (playRadio.isSelected()) {
			remove(entryPanel);
			add(controlPanel, BorderLayout.SOUTH);
			add(topPanel, BorderLayout.CENTER);
			regenerateBoard();
			repaint();
		} else if (solveRadio.isSelected()) {
			int[][] blankNums = new int[9][9];
			for (int x = 0; x < 9; x++) {
				for (int y = 0; y < 9; y++) {
					blankNums[x][y] = 0;
				}
			}
			b.userBoard = blankNums;
			remove(entryPanel);
			add(controlPanel, BorderLayout.SOUTH);
			add(topPanel, BorderLayout.CENTER);
			regenerateBoard();
			checkButton.setText("Solve");
			remove(newButton);
			newButton.setVisible(false);
			remove(difButton);
			difButton.setVisible(false);
			repaint();

		}
	}

	private void changeNumber(Object source) {
		for (int x = 0; x < 9; x++) {
			for (int y = 0; y < 9; y++) {
				if (source == tiles[x][y]) {
					int num = Integer.valueOf(tiles[x][y].getText());
					System.out.println("Chenaged");
					if (num > 0 && num < 10) {
						tiles[x][y].setNum(num);
						nums[x][y] = num;
						tiles[x][y].setEnabled(false);
						tiles[x][y].setEnabled(true);

						b.userBoard[x][y] = num;
					} else {
						tiles[x][y].setNum(b.userBoard[x][y]);
					}
				}
			}
		}
	}

	private void regenerateBoard() {
		for (int x = 0; x < 9; x++) {
			for (int y = 0; y < 9; y++) {

				tiles[x][y].setOrigNum(b.userBoard[x][y]);
				tiles[x][y].setNum(b.userBoard[x][y]);

				panels[x / 3][y / 3].add(tiles[x][y]);
			}
		}
	}
}